/*
 *  Copyright (C) 2010 Matthias Buch-Kromann <mbk.isv@cbs.dk>
 * 
 *  This file is part of the MatrixParser package.
 *  
 *  The MatrixParser program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 * 
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.osdtsystem.matrixparser.parsers;

import java.io.IOException;
import java.io.Writer;
import org.osdtsystem.matrixparser.features.TwoWayFeatureHandler;
import org.osdtsystem.matrixparser.logging.Log;

/**
 *
 * @author Matthias Buch-Kromann <mbk.isv@cbs.dk>
 */
public class ActionMoveEdge extends Action implements Comparable<ActionMoveEdge> {
    double oldEFscore, newEFscore;
    int[] affected;
    double[] newScores, oldScores;

    ActionMoveEdge(double delta, double oldEFscore, double newEFscore,
            int node, int oldhead, int oldtype, int newhead, int newtype,
            int[] affected, double[] newScores, double[] oldScores) {
        super(delta, node, oldhead, oldtype, newhead, newtype);
        this.oldEFscore = oldEFscore;
        this.newEFscore = newEFscore;
        this.affected = affected;
        this.newScores = newScores;
        this.oldScores = oldScores;
    }

    void apply(IncrementalLabMSTParser parser, IncrementalLabMSTParser.ParseState state) {
        state.tree.setDependency(node(), newhead(), newtype());
        parser.restoreNonEFScores(state, affected, newScores);
        state.scores1stOrder[node()] = newEFscore;
    }

    void unapply(IncrementalLabMSTParser parser, IncrementalLabMSTParser.ParseState state) {
        state.tree.setDependency(node(), oldhead(), oldtype());
        parser.restoreNonEFScores(state, affected, oldScores);
        state.scores1stOrder[node()] = oldEFscore;
    }

    final void log(String affix) {
        if (Log.debugParserActions)
           System.err.println("" + node() + ": head=" + newhead() + " type=" + newtype() + affix);
    }
    
    final int node() { return action[0]; }
    final int oldhead() { return action[1]; }
    final int oldtype() { return action[2]; }
    final int newhead() { return action[3]; }
    final int newtype() { return action[4]; }

    public int compareTo(ActionMoveEdge o) {
        if (node() < o.node())
            return -1;
        if (node() > o.node())
            return 1;
        if (newhead() < o.newhead())
            return -1;
        if (newhead() > o.newhead())
            return 1;
        if (newtype() < o.newtype())
            return -1;
        if (newtype() > o.newtype())
            return 1;
        return 0;
    }

    @Override
    public void writeAsDTAG(Writer writer, TwoWayFeatureHandler labelAlphabet) throws IOException {
        if (oldhead() >= 0)
            writer.append("edel ").append("" + node()).append(" ").append(labelAlphabet.getName(oldtype()))
                    .append(" ").append("" + oldhead()).append("\n");
        writer.append("" + node()).append(" ").append(labelAlphabet.getName(newtype()))
                .append(" ").append("" + newhead()).append("\n");
        writer.append("edit ").append("" + node())
                .append(" score1=\"").append(String.format("%.6g", newEFscore))
                .append("\" delta1=\"").append(String.format("%.6g", newEFscore - oldEFscore))
                .append("\"\n");
        for (int node : affected) {
            if (node >= 0 && node < newScores.length)
                writer.append("edit ").append("" + node())
                    .append(" score2=\"").append(String.format("%.6g", newScores[node]))
                    .append("\" delta2=\"").append(String.format("%.6g", newScores[node] - oldScores[node]))
                    .append("\"\n");
        }
    }
}
